package com.whz.iplocation.http;

import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.Map;
import java.util.function.Function;

/**
 * @author whz
 */
@UtilityClass
public class HttpClientUtils {
    public static final CloseableHttpClient CLIENT = HttpClientFactoryUtils.creatDefaultHttpClient();

    /**
     * 查询ip数据库的方法
     *
     * @param url 地址
     * @return 字节数组
     */
    @SneakyThrows
    public static byte[] getIpDataBase(String url) {
        HttpGet get = new HttpGet(url);
        /*
         * 注意这两个header,可能有变化 参考 https://github.com/jarod/qqwry-java/blob/master/src/main/java/com/github/jarod/qqwry/QQWry.java
         */
        get.setHeader("Accept", "text/html, */*");
        get.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0");
        return CLIENT.execute(get, getByteResponseHandler());
    }

    @SneakyThrows
    public static byte[] get(String url) {
        HttpGet get = new HttpGet(url);
        return CLIENT.execute(get, getByteResponseHandler());
    }

    /**
     * post http request with json body,return string (json)
     *
     * @param url    url
     * @param params params
     * @return string
     */
    @SneakyThrows
    public String postJsonBody(String url, Map<String, Object> params) {
        HttpPost httpPost = buildPostRequest(url, params);
        return CLIENT.execute(httpPost, getStringResponseHandler());
    }

    /**
     * post http request with json body, return byte[]
     *
     * @param url    url
     * @param params params
     * @return byte[]
     */
    @SneakyThrows
    public byte[] postReturnByte(String url, Map<String, Object> params) {
        HttpPost httpPost = buildPostRequest(url, params);
        return CLIENT.execute(httpPost, getByteResponseHandler());
    }

    private HttpPost buildPostRequest(String url, Map<String, Object> params) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
        // 解决中文乱码问题
        StringEntity stringEntity = new StringEntity(JSON.toJSONString(params), "UTF-8");
        stringEntity.setContentEncoding("UTF-8");
        httpPost.setEntity(stringEntity);
        return httpPost;
    }


    private ResponseHandler<String> getStringResponseHandler() {
        return getResponseHandler(httpEntity -> {
            try {
                return EntityUtils.toString(httpEntity);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private ResponseHandler<byte[]> getByteResponseHandler() {
        return getResponseHandler(httpEntity -> {
            try {
                return EntityUtils.toByteArray(httpEntity);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }


    private <T> ResponseHandler<T> getResponseHandler(Function<HttpEntity, T> function) {
        // Create a custom response handler
        return response -> {
            int status = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            if (status >= 200 && status < 300) {
                return entity != null ? function.apply(entity) : null;
            } else {
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
        };
    }
}